#include "EventLoop.hpp"

EventLoop::EventLoop() :
    isQuit_(false),
    isLooping_(false),
    isEventHandling_(false) {

    loopId_ = std::to_string(std::hash<std::thread::id>{}(std::this_thread::get_id()));
    // 初始化eventfd
    eventFd_ = eventfd(0, EFD_NONBLOCK | EFD_CLOEXEC);
    // 检查返回值
    if (eventFd_ < 0) {
        perror("eventfd");
        LOG << "Failed to create eventfd";
        abort();
    }
    eventChannel_ = std::make_shared<Channel>(eventFd_);
    eventChannel_->set_read_handler(std::bind(&EventLoop::handleRead, this));
    eventChannel_->setEvents(EPOLLIN | EPOLLET);

    poller_ = std::make_shared<Poller>();
    poller_->epoll_add(eventChannel_);

    functions.reserve(4096); // 预留空间，避免频繁扩容
}

EventLoop::~EventLoop() {
    // 确保事件循环停止
    if (isLooping_.load()) {
        stopLoop();
    }
    eventChannel_->closeChannel();// 关闭eventfd
}

void EventLoop::startLoop() {

    // 开始事件循环 调用该函数的线程必须是该EventLoop所在线程 
    assert(!isLooping_.load());
    isLooping_ = true;
    isQuit_ = false;
    while (!isQuit_.load(std::memory_order_acquire)) {  // 原子加载
        // 1、epoll_wait阻塞 等待就绪事件
        // auto tp0 = std::chrono::high_resolution_clock::now();
        std::vector<ChannelPtr> active_channels;
        poller_->poll(active_channels);
        // if (active_channels.size() > 100)
        //     LOGW << "active_channels.size(): " << active_channels.size();

        // 2、处理每个就绪事件(不同channel绑定了不同的callback)
        // auto tp1 = std::chrono::high_resolution_clock::now();
        isEventHandling_ = true;
        for (auto& channel : active_channels) {
            if (channel->isValid()) {  // 增加有效性检查
                channel->handleEvents();
            }
            else {
                std::cerr << "EventLoop::startLoop() error: invalid channel, " << "fd: " << channel->getFd() << std::endl;
                removeChannel(channel);  // 清理无效Channel
            }
        }
        isEventHandling_ = false;

        // 3、执行正在等待的函数(fd注册到epoll内核事件表)
        // auto tp2 = std::chrono::high_resolution_clock::now();
        // functions.clear();
        int num = 0;
        {
            // std::lock_guard<std::mutex> lock(pf_swap_mutex_);
            // // 交换的方式减少了锁的临界区范围，提升效率
            // functions.swap(pendingFunctions_);
            Function func;
            while (pendingFunctions_.pop(func)) {
                // functions.emplace_back(std::move(func));
                func();
                num++;
            }
        }
        // // 执行所有等待的函数
        // for (const auto& func : functions) {
        //     func();
        // }

        // 4、处理超时事件 到期了就从定时器小根堆中删除(定时器析构会EpollDel掉fd)
        // poller_->HandleExpire();

        // auto tp3 = std::chrono::high_resolution_clock::now();
        // auto duration1 = std::chrono::duration_cast<std::chrono::microseconds>(tp1 - tp0).count();
        // auto duration2 = std::chrono::duration_cast<std::chrono::microseconds>(tp2 - tp1).count();
        // auto duration3 = std::chrono::duration_cast<std::chrono::microseconds>(tp3 - tp2).count();
        // if (active_channels.size() >= 10 || num >= 5)
        //     std::cout << "一次Loop循环中，epoll_wait阻塞: " << duration1 << "μs，处理 " << active_channels.size() << " 个就绪事件: " << duration2 << "μs，执行正在等待的函数 " << num << " 个: " << duration3 << "μs" << std::endl;
    }
    // 退出时清理
    LOG << "EventLoop stop looping" << std::endl;
    isLooping_.store(false);
    // isLooping_ = false;
}

void EventLoop::stopLoop() {
    isQuit_.store(true, std::memory_order_release);  // 原子存储
    wakeUp();
    // if (!is_in_loop_thread()) {
    //     wakeUp();// 确保跨线程唤醒
    // }
}

void EventLoop::queueInPendingFunctions(Function&& func) {
    {
        // std::lock_guard<std::mutex> lock(pf_swap_mutex_);
        // pendingFunctions_.emplace_back(std::move(func));
        while (!pendingFunctions_.push(std::move(func)));;
    }
    /*
    wakeUp 的调用条件 if (!is_calling_pending_functions_ && !isEventHandling_) 是为了避免不必要的 write eventfd。但在高并发下，如果一个任务在处理事件 (isEventHandling_ = true) 或执行其他待处理任务 (is_calling_pending_functions_ = true) 时被添加，WakeUp 可能不会被调用。这可能导致新连接的 addChannel 任务被延迟处理。虽然不直接导致 fd 泄漏，但可能影响响应和处理效率。通常，如果调用 queueInPendingFunctions 的线程不是 EventLoop 所在的线程，就应该无条件 WakeUp，让 eventfd 和 epoll 机制去处理唤醒。
    */
    wakeUp();
    // if (!is_calling_pending_functions_ && !isEventHandling_) {
    //     wakeUp();
    // }
}

void EventLoop::addChannel(ChannelPtr channel) {
    if (isLooping_.load()) {
        poller_->epoll_add(channel);
    }
    else {
        LOG << "EventLoop::addChannel() error";
    }
}
void EventLoop::removeChannel(ChannelPtr channel) {
    LOG << "EventLoop::removeChannel() fd: " << channel->getFd();
    if (isLooping_.load()) {
        poller_->epoll_del(channel);
    }
    else {
        LOG << "EventLoop::removeChannel() error";
    }
}

// 被唤醒之后处理eventfd值累积问题
// 因为eventfd是一个计数器，每次读都会清零，所以需要不断读取直到读完所有事件通知？？？？？？？？？？？？？？？？？？？？？？？？
// 否则可能会导致事件丢失或者重复处理
void EventLoop::handleRead() {
    uint64_t one;
    ssize_t n = 0;

    // 完全读取所有事件通知
    while ((n = read(eventFd_, &one, sizeof one)) > 0) {
        // 避免eventfd值累积
    }
    if (n < 0 && errno != EAGAIN) {
        LOG << "EventLoop::handleRead() error";
    }
}


void EventLoop::wakeUp() {
    uint64_t one = 1;
    ssize_t n = 0;
    // 确保完整写入
    while ((n = write(eventFd_, &one, sizeof one)) < 0 && errno == EINTR) {
        // 处理中断重试
    }
    if (n != sizeof one) {
        perror("write eventFd_");
        LOG << "EventLoop::wakeUp() writes error";
    }
}
